home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / c / library / bcfamily / source / suballoc.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-12  |  4.1 KB  |  189 lines

  1. //
  2. //      *******************************************************************
  3. //        JdeBP C++ Library Routines          General Public Licence v1.00
  4. //            Copyright (c) 1991,1992     Jonathan de Boyne Pollard
  5. //      *******************************************************************
  6. //
  7. // Part of FamAPI.LIB
  8. //
  9.  
  10. #include "famapi.h"
  11. #include "dosdos.h"
  12.  
  13. //
  14. //    A segment set up for sub-allocation has the pointer to the first free
  15. //    block (offset only) in the first USHORT of the segment, and the segment
  16. //    size in the second.
  17. //
  18. //    The free blocks are NOT sorted.
  19. //
  20.  
  21. struct SubAllocSeg {
  22.     USHORT NextOffset ;            // Next free block
  23.     USHORT Size ;                // Size (rounded up)
  24. } ;
  25.  
  26. //
  27. //    The following was defined for testing the suballocation routines in
  28. //    protected mode.  All allocated and freed blocks of memory, and all
  29. //    segments after resizing, were cleared with zeros.  This caught several
  30. //    pointer errors.
  31. //
  32.  
  33. #define    BE_A_REAL_BASTARD    0
  34.  
  35. //
  36. //    Allocate memory
  37. //
  38. USHORT _APICALL
  39. DosSubAlloc    ( USHORT Selector,
  40.               USHORT far *PtrOffset,
  41.               USHORT Size )
  42. {
  43.     struct SubAllocSeg far *sptr =
  44.         (struct SubAllocSeg far *)MK_FP(Selector, 0) ;
  45.  
  46.     // Size is rounded up to next multiple of a long word
  47.  
  48.     ULONG LSize = (Size + 3UL) & ~3UL ;
  49.  
  50.     while (sptr->NextOffset != 0) {
  51.  
  52.         struct SubAllocSeg far *lastptr = sptr ;
  53.  
  54.         FP_OFF(sptr) = sptr->NextOffset ;
  55.  
  56.         if (sptr->Size > LSize) {
  57.  
  58.             // Allocate off the tail of the block
  59.  
  60.             sptr->Size -= LSize ;
  61.             *PtrOffset = FP_OFF(sptr) + sptr->Size ;
  62.  
  63. #if BE_A_REAL_BASTARD
  64.             //
  65.             //    Bastard debugging code to provoke errors
  66.             //
  67.             UCHAR far *p = (UCHAR far *)MK_FP(Selector, *PtrOffset) ;
  68.             while (LSize-- > 0)
  69.                 *p++ = 0 ;
  70. #endif
  71.  
  72.             return NO_ERROR ;
  73.  
  74.         } else if (sptr->Size == LSize) {
  75.  
  76.             // Pull the heap record off the free list
  77.  
  78.             lastptr->NextOffset = sptr->NextOffset ;
  79.             *PtrOffset = FP_OFF(sptr) ;
  80.  
  81. #if BE_A_REAL_BASTARD
  82.             //
  83.             //    Bastard debugging code to provoke errors
  84.             //
  85.             UCHAR far *p = (UCHAR far *)MK_FP(Selector, *PtrOffset) ;
  86.             while (LSize-- > 0)
  87.                 *p++ = 0 ;
  88. #endif
  89.  
  90.             return NO_ERROR ;
  91.  
  92.         }
  93.     }
  94.  
  95.     return ERROR_NOT_ENOUGH_MEMORY ;
  96. }
  97.  
  98. //
  99. //    Free memory
  100. //
  101. USHORT _APICALL
  102. DosSubFree    ( USHORT Selector,
  103.               USHORT Offset,
  104.               USHORT Size )
  105. {
  106.     struct SubAllocSeg far *headptr =
  107.         (struct SubAllocSeg far *)MK_FP(Selector, 0) ;
  108.     struct SubAllocSeg far *freeptr =
  109.         (struct SubAllocSeg far *)MK_FP(Selector, Offset) ;
  110.  
  111.     // Size is rounded up to next multiple of a long word
  112.  
  113.     ULONG LSize = (Size + 3UL) & ~3UL ;
  114.  
  115.     freeptr->Size = LSize ;
  116.     freeptr->NextOffset = headptr->NextOffset ;
  117.     headptr->NextOffset = Offset ;
  118.  
  119. #if BE_A_REAL_BASTARD
  120.     //
  121.     //    Bastard debugging code to provoke errors
  122.     //
  123.     UCHAR far *p = (UCHAR far *)MK_FP(Selector, Offset + 4) ;
  124.     LSize -= 4 ;
  125.     while (LSize-- > 0)
  126.         *p++ = 0 ;
  127. #endif
  128.  
  129.     return NO_ERROR ;
  130. }
  131.  
  132. //
  133. //    Initialise/Reinitialise a sub-allocated segment
  134. //
  135. USHORT _APICALL
  136. DosSubSet    ( USHORT Selector,
  137.               USHORT Flags,
  138.               USHORT Size )
  139. {
  140.     //
  141.     //    Because the SubAlloc and SubFree functions round UP to the next
  142.     //    multiple of a long word, this must round the overall size DOWN,
  143.     //    lest the three or less bytes at the end are allocated as a
  144.     //    whole long word, and fencepost errors result.
  145.     //
  146.  
  147.     ULONG LSize = (Size - 1UL) & ~3UL ;
  148.  
  149.     struct SubAllocSeg far *headptr =
  150.         (struct SubAllocSeg far *)MK_FP(Selector, 0) ;
  151.  
  152.     if (Flags == 1) {
  153.         headptr->Size = (USHORT) LSize ;
  154.  
  155.         if (LSize > 4) {
  156.             headptr->NextOffset = 4 ;
  157.             headptr++ ;
  158.             headptr->Size = (USHORT) (LSize - 4) ;
  159.             headptr->NextOffset = (USHORT) 0 ;        // Signal last free block
  160.  
  161. #if BE_A_REAL_BASTARD
  162.             //
  163.             //    Bastard debugging code to provoke errors
  164.             //
  165.             UCHAR far *p = (UCHAR far *)(headptr + 1) ;
  166.             LSize -= 8 ;
  167.             while (LSize-- > 0)
  168.                 *p++ = 0 ;
  169. #endif
  170.  
  171.         } else
  172.             headptr->NextOffset = 0 ;
  173.  
  174.     } else {
  175.  
  176.         if (headptr->Size < LSize) {
  177.  
  178.             USHORT EndOffset = headptr->Size ;
  179.  
  180.             headptr->Size = (USHORT) LSize ;
  181.  
  182.             return DosSubFree(Selector, EndOffset, (USHORT) (LSize - EndOffset)) ;
  183.  
  184.         } else
  185.             headptr->Size = (USHORT) LSize ;
  186.     }
  187.  
  188.     return NO_ERROR ;
  189. }